package net.quanter.shield.common.dto.result.wapper;

import java.io.Serializable;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.ToString;
import net.quanter.shield.common.dto.result.ResultDTO;
import org.jetbrains.annotations.NotNull;

/**
 * Set类型通用返回DTO
 *
 * @author 王老实
 * @since 1.3.12.RELEASE
 */
@Schema(description = "Set类型通用返回DTO")
@ToString
public class ResultDTOSetWapper<T extends Serializable> implements Set<T> {

    @Getter
    private final ResultDTO<Set<T>> resultDTO;

    public ResultDTOSetWapper(ResultDTO<Set<T>> resultDTO) {
        this.resultDTO = resultDTO == null ? emptySet() : resultDTO;
    }

    public static <T extends Serializable> ResultDTO<Set<T>> emptySet() {
        return new ResultDTO<>(new HashSet<>());
    }

    public static <T extends Serializable> ResultDTOSetWapper<T> emptySetWapper() {
        return new ResultDTOSetWapper(emptySet());
    }

    public <N extends Serializable> ResultDTOSetWapper<N> convert(Function<T, N> action) {
        ResultDTO<Set<N>> newResultDTO = new ResultDTO(resultDTO.isSuccess(),resultDTO.getMessage(),resultDTO.getCode(),null);
        Set<N> dataList = resultDTO.get()
                .map(x -> x.stream().map(action).collect(Collectors.toSet()))
                .orElse(new HashSet<>());
        newResultDTO.setData(dataList);
        return new ResultDTOSetWapper(newResultDTO);
    }

    public Set<T> getData() {
        return resultDTO.getData();
    }

    @Override
    public boolean add(T t) {
        return resultDTO.get().map(x -> x.add(t)).orElse(false);
    }

    @Override
    public boolean containsAll(@NotNull Collection<?> c) {
        return resultDTO.get().map(x -> x.containsAll(c)).orElse(false);
    }

    @Override
    public boolean addAll(@NotNull Collection<? extends T> c) {
        return resultDTO.get().map(x -> x.addAll(c)).orElse(false);
    }

    @Override
    public boolean retainAll(@NotNull Collection<?> c) {
        return resultDTO.get().map(x -> x.retainAll(c)).orElse(false);
    }

    @Override
    public boolean remove(Object o) {
        return resultDTO.get().map(x -> x.remove(o)).orElse(false);
    }

    @Override
    public boolean removeAll(@NotNull Collection<?> c) {
        return resultDTO.get().map(x -> x.removeAll(c)).orElse(false);
    }

    @Override
    public boolean removeIf(Predicate<? super T> filter) {
        return resultDTO.get().map(x -> x.removeIf(filter)).orElse(false);
    }

    @Override
    public boolean isEmpty() {
        return resultDTO.get().map(Set::isEmpty).orElse(true);
    }

    @Override
    public boolean contains(Object t) {
        return resultDTO.get().map(x -> x.contains(t)).orElse(false);
    }

    @Override
    public @NotNull Iterator<T> iterator() {
        return resultDTO.get().map(Set::iterator).orElse(Collections.emptyIterator());
    }

    @Override
    public void forEach(Consumer<? super T> action) {
        resultDTO.get().ifPresent(x -> x.forEach(action));
    }

    @Override
    public Object[] toArray() {
        return resultDTO.get().map(Set::toArray).orElse(new HashSet<T>(0).toArray());
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return resultDTO.get().map(x -> x.toArray(a)).orElse(a);
    }

    @Override
    public int size() {
        return resultDTO.get().map(Set::size).orElse(0);
    }

    @Override
    public void clear() {
        resultDTO.get().ifPresent(Set::clear);
    }

    @Override
    public Spliterator<T> spliterator() {
        return resultDTO.get().map(Set::spliterator).orElse(new HashSet<T>(0).spliterator());
    }

    @Override
    public Stream<T> stream() {
        return resultDTO.get().stream().flatMap(Collection::stream);
    }

    @Override
    public Stream<T> parallelStream() {
        return resultDTO.get().stream().flatMap(Collection::parallelStream);
    }
}
